/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#ifndef GRAPH_H
#define GRAPH_H

#include "statManager.h"
#include "node.h"

#include <map>
class Controller;
using namespace std;

class NodeIterator;
class EdgeIterator;
class ElementIterator;

class Graph: public Object {
protected:
    Controller *controller;
    StatManager *stats;
public:
    vector<Node *> nodes;
    map<int, Node*> nodeMap;
    int numEdges;

    Graph(Controller* controller);
    Graph(const char *name, Controller*controller);
    ~Graph();

    void clear();

    void createNodes(int start, int end);
    Node *addNode(Node *n);
    Node * addNode(const char *name);
    Edge * addEdge(int from, int to);
    void computeNodeMinMaxFloat(string name);
    void computeNodeMinMaxInt(string name); //yuhsuan


    void computeEdgeMinMaxFloat(string name);
    void computeEdgeMinMaxInt(string name);//yuhsuan
    void computeEdgeMinMaxBool(string name); //yuhsuan

    void computeImplicitEdgeMinMaxFloat(string name);
    StatManager *getStatManager();
    void setStatManager(StatManager *s);

    // 0817 yuhsuan: to set MinMax outside graph
    void setMinMaxFloat(string name, float minv, float maxv) {
        this->getStatManager()->setMinMaxFloat(name, minv, maxv);
    }
    void getMinMaxFloat(string property, float &minv, float &maxv){
        this->getStatManager()->getMinMaxFloat(property, minv, maxv);
    }

    string getAsString(PropertyBag *bag, string property, string defaultValue = "", bool normalized=true); // retrieves value of property as a string
    float getAsFloat(PropertyBag *bag, string property, float defaultValue = 1.0, bool normalized=true); // retrieves value of property as a float
    float getAsNormalizedFloat(PropertyBag *bag, string property, float defaultValue);
    float getAsSigned(PropertyBag *bag, string property, float defaultValue = 1.0, bool normalized=true); // retrieves value of property as a float
    int getAsInteger(PropertyBag *bag, string property, int defaultValue = 0); // retrieves property as an integer, performing the appropriate conversion according to the property's type. For faster access, use directly the getPropertyFloat/getPropertyInt etc
    bool getAsBoolean(PropertyBag *bag, string property);

    inline unsigned int numNodes() {
        return nodes.size();
    }
    inline Node *getNode(int i) {
        return nodes[i];
    }
    inline Edge *getEdge(int i, int j) {
        return nodes[i]->getEdge(j);
    }
    inline bool hasEdge(int i, int j) {
        return nodes[i]->hasEdge(j);
    }
    inline Edge *getImplicitEdge(int i, int j) {
        return nodes[i]->getImplicitEdge(j);
    }
    NodeIterator *getNeighbors(int i);
    EdgeIterator *getEdges(int i);
    NodeIterator *getNeighbors(Node *n);
    EdgeIterator *getEdges(Node *n);
    NodeIterator *createNodeIterator();
    EdgeIterator *createEdgeIterator();
    void destroyIterator(ElementIterator *it);
};

class ElementIterator {
public:
    ElementIterator() {}
    virtual void begin()=0;
    virtual bool hasMoreElements()=0;
    virtual PropertyBag *next()=0;
};

class NodeIterator:public ElementIterator {
protected:
    int idx;
    int N;
    Graph *graph;
public:
    NodeIterator(Graph *g);
    virtual void begin();
    virtual bool hasMoreElements();
    virtual PropertyBag *next();
};
class EdgeIterator:public ElementIterator {
protected:
    int idx;
    int idxEdge;
    int N;
    Graph *graph;
public:
    EdgeIterator(Graph *g);
    virtual void begin();
    virtual bool hasMoreElements();
    virtual PropertyBag *next();
};

class NeighborIterator:public NodeIterator {
protected:
    Node *node;
public:
    NeighborIterator(Graph *g, Node *n);
    virtual void begin();
    virtual bool hasMoreElements();
    virtual PropertyBag *next();
};
class IncidentEdgeIterator:public EdgeIterator {
protected:
    Node *node;
public:
    IncidentEdgeIterator(Graph *g, Node *n);
    virtual void begin();
    virtual bool hasMoreElements();
    virtual PropertyBag *next();
};



#endif
